﻿#define  _CRT_SECURE_NO_WARNINGS 1

// 猜数字游戏
/*
	游戏要求：1.电脑自动生成1~100的随机数
			 2.玩家猜数字，猜数字的过程中，需要根据用户输入的数字来反馈给用户数字猜大猜小，直到猜对游戏结束。

*/


//											1.随机数生成

//	1.1	rand函数，这个函数可以生成随机数。

// 函数原型： int rand(void);

//rand函数会返回⼀个伪随机数，这个随机数的范围是在0~RAND_MAX之间，这个RAND_MAX的大小是依赖编译器上实现的，但是⼤部分编译器上是32767。
//使用rand函数时需要包含一个头文件是：stdlib.h 
//#include <stdio.h>
//#include <stdlib.h>
//int main()
//{
//	RAND_MAX; // 转到定义是0x7FFF，转为十进制是32767
//	return 0;
//}
//
//int main()
//{
//	printf("%d\n", rand()); // rand函数不需要参数。
//	printf("%d\n", rand());
//	printf("%d\n", rand());
//	printf("%d\n", rand());
//	printf("%d\n", rand());
//	printf("%d\n", rand());
//	return 0;
//	/*
//	 以上程序中可以看到，即使是rand生成随机数，但是重复运行几次代码就会发现每次运行出来的结果都是固定的.
//	 其实rand函数⽣成的随机数是伪随机的，伪随机数不是真正的随机数，是通过某种算法⽣成的随机数。
//	 真正的随机数的是⽆法预测下⼀个值是多少的。⽽rand函数是对⼀个叫“种子”的基准值进⾏运算⽣成的随机数。
//	之所以前⾯每次运⾏程序产⽣的随机数序列是⼀样的，那是因为rand函数⽣成随机数的默认种子是1。
//如果要生成不同的随机数，就要让种子是变化的。
//
//	*/
//}



//	1.2 srand


/*
	C语⾔中又提供了⼀个函数叫 srand，⽤来初始化随机数的生成器的。
	基本原型：1 void srand (unsigned int seed); seed是种子
	程序中在调用 rand 函数之前先调用 srand 函数，通过 srand 函数的参数seed来设置rand函数生成随机数的时候的种子。
	只要种子在变化，每次生成的随机数序列也就变化起来了。

那也就是说给srand的种⼦是如果是随机的，rand就能生成随机数；在生成随机数的时候又需要⼀个随机数，这就矛盾了



*/

//int main()
//{
//	srand(1);
//	printf("%d\n", rand());
//	printf("%d\n", rand());
//	printf("%d\n", rand());
//	return 0;
//
//	// 可以看到当基准值设置成1时，结果与上次完全一致，因为上边没有srand(),种子默认为1.
//}

//int main()
//{
//	srand(2);
//	printf("%d\n", rand());
//	printf("%d\n", rand());
//	printf("%d\n", rand());
//	return 0;
//
//	// 可以看到当基准值设置成2时，结果与srand(1)就不一致了，但是多重复几遍，srand(2)的结果每次都相同
//}

// 由以上例子可以看出来，想要每次都生成一个随机数，就要确保每次的基准值都是随机的。
// 但是用随机数来确保随机数有点套娃，因此只要保证这个基准值每次不一样就行，不一定要随机值。因此可以使用时间作为种子，因为时间时刻都在变化。




//		1.3 time

/*

在程序中我们⼀般是使⽤程序运⾏的时间作为种⼦的，因为时间时刻在发⽣变化的。
在C语⾔中有⼀个函数叫 time ，就可以获得这个时间，time函数原型如下：

	time_t time (time_t* timer);

	time函数可以返回一个时间戳。时间戳指的是：1970年1⽉1⽇0时0分0秒到现在程序运行时间之间的差值，单位是秒

	time 函数会返回当前的日历时间，其实返回的是1970年1⽉1⽇0时0分0秒到现在程序运行时间之间的差值，单位是秒。
返回的类型是time_t类型的，time_t 类型本质上其实就是32位或者64位的整型类型。

其中time_t*是一个指针类型，time_t是函数返回值类型，是时间类型，但是本质是无符号整型类型


	time函数的参数 timer 如果是⾮NULL的指针的话，函数也会将这个返回的差值放在timer指向的内存中带回去。

	如果 timer 是NULL，就只返回这个时间的差值。time函数返回的这个时间差也被叫做：时间戳

	time函数的时候需要包含头⽂件：time.h

	time(NULL);//调⽤time函数返回时间戳，这里没有接收返回值
*/

//#include <stdio.h>
//#include <stdlib.h>
//#include <time.h>
//int main()
//{
//	srand((unsigned int)time(NULL)); // 这样就可以返回一个时刻都在变化的时间戳了
//	// srand的返回的类型是unsigned int，而time的返回值类型是time_t，类型不匹配编译器可能会报警告，为了防止这种情况，干脆直接强转了。
//	printf("%d\n", rand());
//	printf("%d\n", rand());
//	printf("%d\n", rand());
//	return 0;
//}

//											1.4 设置随机数的范围

/*
	如果我们要生成0~99之间的随机数，方法如下：

	rand() %100;//一个数取余100的所有结果是0~99

	如果我们要生成1~100之间的随机数，方法如下：

	rand() %100+1;//一个数取余100的所有结果是0~99，此时加一就是左右两边同时加一，得到结果是1~100

	由上可得：

	如果我们要生成a~b之间的随机数，方法如下：

	1.  rand() %(b+1);
	//先取余b+1得到b之前的余数，此时范围是0~b.

	2.  rand() %(b+1) + a;
	//但是最小值要从a开始，因此可以左右两边的数字同时加a,得到的范围就是a~b+a.

	3. rand() %(b-a+1) + a;
	// 想要解决这个问题，就要把左边的范围减去一个a,此时范围正好

	简洁版：想要生成a~b的范围，就需要生成的余数范围控制在[0~b-a]，所以需要rand() %(b-a+1)，此时再加a的范围就控制在了[a~b]

*/



// 正式开始


#include <stdio.h>    // 输入输出需要包含的头文件
#include <stdlib.h>  // rand()和srand()需要包含的头文件
#include <time.h>    // time()需要包含的头文件

void menu()  // 游戏菜单
{
	printf("*************************\n");
	printf("*****选择游戏是否开始：*****\n");
	printf("*****play:请输入1**********\n");
	printf("*****exit:请输入0**********\n");
	printf("**************************\n");
}
void game()
{
	int guess = 0;   // 定义用户自己输入的值
	int ret = rand() % 100 + 1;   // 将随机值的范围限制在1~100，并将随机值赋值给ret变量
	while (1)//由于不清楚要循环几次用户才会猜对，直接死循环，直到猜对退出循环
	{
		printf("请输入你的数字:");
		scanf("%d", &guess);  // 输出猜的值
		if (ret > guess)
		{
			printf("数字小咯\n");
		}
		else if (ret < guess)
		{
			printf("数字大咯\n");
		}
		else
		{
			printf("猜对咯，随机数是%d\n", ret);
			break;
		}
	}
}
int main()
{
	int input = 0;  // 输入数据0或1表示是否开始游戏
	srand((unsigned int)time(NULL));
	/*
	将srand函数放在主函数中只初始化一次，若是放在自定义函数game()中，则每次游戏开始都会初始化一次srand.
	若是用户短时间内连续开始新的游戏，时间戳的值可能会保持不变，导致每次随机数结果相同。
	*/
	do
	{
		menu(); // 调用菜单函数
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();   // 输入的值为1，调用game函数开始游戏
			break;
		case 0:
			printf("游戏结束");    // 输入0退出游戏
			break;
		default:
			printf("输入无效，请重新输入\n");
		}
	} while (input);
	return 0;
}